/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <flgrCoreDispatch.h>
#include <flgrCoreIO.h>
#include <flgrCoreSlideWindow.h>
#include <flgrCoreNhbManage.h>
#include "flgrLinearKerOp.h"




///////////////////////////////////////////////////////////////////////////
// Macro for different type for flgr1d_get_nhb_convolution function
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_GET_NHB_CONV_1D(dtype)			\
  int i,k;							\
  int spp = extr->spp;						\
  dtype *presult = (dtype *) result->array;			\
  dtype *list_data_val;						\
  dtype *list_nhb_val;						\
  int *size = extr->size;					\
  fgFLOAT64 a,b,sum;						\
  fgFLOAT64 tmp=0;						\
								\
								\
  for(k=0 ; k<spp ; k++) {					\
    list_data_val = (dtype *) extr->list_data_val[k];		\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];		\
								\
    tmp=0;							\
    sum=0;							\
								\
    for(i=0 ; i<size[k] ; i++){					\
      a = (fgFLOAT64) list_data_val[i];				\
      b = (fgFLOAT64) list_nhb_val[i];				\
      tmp += a*b;						\
      sum += (b<0) ? 0 : b;					\
    }								\
    flgr_set_array_##dtype(presult,k,(dtype) (tmp/sum));	\
  }								\
								\
  return



void flgr1d_get_nhb_convolution_fgBIT(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr1d_get_nhb_convolution_fgUINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgUINT8);
}
void flgr1d_get_nhb_convolution_fgUINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgUINT16);
}
void flgr1d_get_nhb_convolution_fgUINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgUINT32);
}
void flgr1d_get_nhb_convolution_fgINT8(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgINT8);
}
void flgr1d_get_nhb_convolution_fgINT16(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgINT16);
}
void flgr1d_get_nhb_convolution_fgINT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgINT32);
}
void flgr1d_get_nhb_convolution_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgFLOAT32);
}
void flgr1d_get_nhb_convolution_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_MACRO_GET_NHB_CONV_1D(fgFLOAT64);
}
//////////////////////////////////////////////////////////////////
/*! Compute convolution
 *  @param nhb : a pointer to FLGR_Data1D
 *  @param sigma : a float value
 *  @param levelMax  : a float value
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr1d_get_nhb_convolution(FLGR_Vector *result, FLGR_NhbBox1D *extr) {
  FLGR_DECLARE_FUNCTION;

  if(result==NULL){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(extr==NULL){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(result->type,flgr1d_get_nhb_convolution,result,extr);
}













///////////////////////////////////////////////////////////////////////////
// Macro for different type of flgr2d_get_nhb_convolution function
//////////////////////////////////////////////////////////////////
#define FLGR_MACRO_GET_NHB_CONV_2D(dtype)			\
  int i,k;							\
  int spp = extr->spp;						\
  dtype *presult = (dtype *) result->array;			\
  dtype *list_data_val;						\
  dtype *list_nhb_val;						\
  int *size = extr->size;					\
  fgFLOAT64 a,b,sum=0;						\
  fgFLOAT64 tmp=0;						\
								\
								\
  for(k=0 ; k<spp ; k++) {					\
    list_data_val = (dtype *) extr->list_data_val[k];		\
    list_nhb_val = (dtype *) extr->list_nhb_val[k];		\
								\
    tmp=0;							\
    sum=0;							\
								\
    for(i=0 ; i<size[k] ; i++){					\
      a = (fgFLOAT64) list_data_val[i];				\
      b = (fgFLOAT64) list_nhb_val[i];				\
      tmp += a*b;						\
      sum += (b<0) ? 0 : b;					\
    }								\
    flgr_set_array_##dtype(presult,k,(dtype) (tmp/sum));	\
  }								\
								\
  return



void flgr2d_get_nhb_convolution_fgBIT(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  flgr_no_define_type_function(FLGR_BIT);
}
void flgr2d_get_nhb_convolution_fgUINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgUINT8);
}
void flgr2d_get_nhb_convolution_fgUINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgUINT16);
}
void flgr2d_get_nhb_convolution_fgUINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgUINT32);
}
void flgr2d_get_nhb_convolution_fgINT8(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgINT8);
}
void flgr2d_get_nhb_convolution_fgINT16(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgINT16);
}
void flgr2d_get_nhb_convolution_fgINT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgINT32);
}
void flgr2d_get_nhb_convolution_fgFLOAT32(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgFLOAT32);
}
void flgr2d_get_nhb_convolution_fgFLOAT64(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_MACRO_GET_NHB_CONV_2D(fgFLOAT64);
}
//////////////////////////////////////////////////////////////////
/*! Compute convolution
 *  @param nhb : a pointer to FLGR_Data2D
 *  @param sigma : a float value
 *  @param levelMax  : a float value
 *  @returns FLGR_RET_OK, ...
 */
//////////////////////////////////////////////////////////////////
FLGR_Ret flgr2d_get_nhb_convolution(FLGR_Vector *result, FLGR_NhbBox2D *extr) {
  FLGR_DECLARE_FUNCTION;

  if(result==NULL){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  if(extr==NULL){
    POST_ERROR("Null objects!\n");
    return FLGR_RET_NULL_OBJECT;
  }

  FLGR_DISPATCH_PROCEDURE(result->type,flgr2d_get_nhb_convolution,result,extr);
}



